package com.example.testplatform.controller;

import com.example.testplatform.common.JwtTokenUtil;
import com.example.testplatform.common.LogUtils;
import com.example.testplatform.common.Result;
import com.example.testplatform.entity.LoginRequest;
import com.example.testplatform.entity.User;
import com.example.testplatform.service.UserService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.HashMap;
import java.util.Map;

/**
 * 登录控制器
 */
@RestController
@RequestMapping("/auth")
@Tag(name = "登录认证", description = "用户登录、注册、登出等认证相关接口")
public class LoginController {

    private static final Logger logger = LogUtils.getLogger(LoginController.class);

    @Autowired
    private UserService userService;

    @Autowired
    private JwtTokenUtil jwtTokenUtil;

    /**
     * 用户登录
     */
    @PostMapping("/login")
    @Operation(summary = "用户登录", description = "用户登录接口")
    public Result<Map<String, Object>> login(@RequestBody LoginRequest loginRequest) {
        long startTime = System.currentTimeMillis();
        LogUtils.logBusiness(logger, "USER_LOGIN_ATTEMPT", "system", "用户登录尝试");
        LogUtils.logSecurityEvent(logger, "USER_LOGIN_REQUEST", "接收到用户登录请求", "请求包含的用户名: " + (loginRequest != null ? loginRequest.getUsername() : "空"));
        LogUtils.debug(logger, () -> "开始处理用户登录请求");
        
        try {
            LogUtils.logApiRequest(logger, "POST", "/auth/login", LogUtils.maskSensitiveInfo(loginRequest != null ? loginRequest.toString() : "空请求"));
            
            // 验证请求对象
            if (loginRequest == null) {
                LogUtils.warn(logger, "登录失败: 登录请求对象为空");
                LogUtils.logBusiness(logger, "USER_LOGIN_FAILED", "system", "登录失败: 登录请求对象为空");
                return Result.fail("登录请求无效");
            }
            
            String username = loginRequest.getUsername();
            String password = loginRequest.getPassword();
            
            LogUtils.debug(logger, () -> "获取登录请求参数: 用户名=" + username + ", 密码=******");

            // 验证参数
            if (!LogUtils.validateParams(logger, username, password)) {
                LogUtils.warn(logger, () -> "登录失败: 用户名或密码为空，请求: " + LogUtils.maskSensitiveInfo(loginRequest.toString()));
                LogUtils.logBusiness(logger, "USER_LOGIN_FAILED", "system", "登录失败: 用户名或密码为空");
                return Result.fail("用户名或密码不能为空");
            }

            LogUtils.info(logger, () -> "尝试登录用户: " + username);
            // 用户登录
            User user = userService.login(username, password);
            if (user == null) {
                LogUtils.warn(logger, "登录失败: 用户名或密码错误，用户名: {}", username);
                LogUtils.logBusiness(logger, "USER_LOGIN_FAILED", "system", "登录失败: 用户名或密码错误，用户名=" + username);
                LogUtils.logSecurityEvent(logger, "USER_LOGIN_FAILED", username, "登录失败: 用户名或密码错误");
                return Result.fail("用户名或密码错误");
            }
            
            LogUtils.info(logger, () -> "用户登录验证通过: 用户名=" + username + ", 用户ID=" + user.getId() + ", 角色=" + user.getRole());

            // 生成JWT令牌
            Map<String, Object> claims = new HashMap<>();
            claims.put("userId", user.getId());
            claims.put("username", user.getUsername());
            claims.put("role", user.getRole());
            LogUtils.debug(logger, () -> "准备生成JWT令牌，用户ID: " + user.getId());
            String token = jwtTokenUtil.generateToken(username, claims);
            
            LogUtils.debug(logger, () -> "JWT令牌生成成功: 令牌长度=" + (token != null ? token.length() : 0) + "字符");

            // 返回结果
            Map<String, Object> result = new HashMap<>();
            result.put("token", token); // 返回真实的token给前端
            result.put("userInfo", user);
            
            // 日志中记录token时进行脱敏处理
            String maskedToken = token != null ? token.substring(0, 10) + "****" + token.substring(token.length() - 10) : "null";
            
            LogUtils.logBusiness(logger, "USER_LOGIN_SUCCESS", "system", "用户登录成功: 用户名=" + username + ", 用户ID=" + user.getId() + ", 角色=" + user.getRole() + ", token=" + maskedToken);
            LogUtils.logSecurityEvent(logger, "USER_LOGIN", username, "登录成功，用户角色: " + user.getRole());
            LogUtils.logPerformance(logger, "login", startTime, System.currentTimeMillis());
            
            LogUtils.info(logger, () -> "登录请求处理完成，耗时=" + (System.currentTimeMillis() - startTime) + "ms");
            return Result.success(result);
        } catch (Exception e) {
            LogUtils.logApiError(logger, "POST", "/auth/login", e);
            LogUtils.error(logger, "登录过程发生异常: " + LogUtils.formatException(e));
            LogUtils.logBusiness(logger, "USER_LOGIN_FAILED", "system", "登录过程发生异常: " + LogUtils.formatException(e));
            LogUtils.logPerformance(logger, "login", startTime, System.currentTimeMillis());
            return Result.fail("登录失败: " + e.getMessage());
        }
    }

    /**
     * 用户注册
     */
    @PostMapping("/register")
    @Operation(summary = "用户注册", description = "用户注册接口")
    public Result<Boolean> register(@RequestBody User user) {
        long startTime = System.currentTimeMillis();
        LogUtils.logBusiness(logger, "USER_REGISTER_ATTEMPT", "system", "用户注册尝试");
        LogUtils.logSecurityEvent(logger, "USER_REGISTER_REQUEST", "接收到用户注册请求", "请求包含的用户名: " + (user != null ? user.getUsername() : "空"));
        LogUtils.debug(logger, () -> "开始处理用户注册请求");
        
        try {
            LogUtils.logApiRequest(logger, "POST", "/auth/register", LogUtils.maskSensitiveInfo(user != null ? user.toString() : "空请求"));
            
            // 验证请求对象
            if (user == null) {
                LogUtils.warn(logger, "注册失败: 用户信息对象为空");
                LogUtils.logBusiness(logger, "USER_REGISTER_FAILED", "system", "注册失败: 用户信息对象为空");
                return Result.fail("用户信息无效");
            }
            
            LogUtils.debug(logger, () -> "获取注册请求参数: 用户名=" + user.getUsername() + ", 真实姓名=" + user.getRealName() + ", 手机号=" + user.getPhone() + ", 邮箱=" + user.getEmail());

            // 验证参数
            if (!LogUtils.validateParams(logger, user.getUsername(), user.getPassword())) {
                LogUtils.warn(logger, () -> "注册失败: 用户名或密码为空，请求: " + LogUtils.maskSensitiveInfo(user.toString()));
                LogUtils.logBusiness(logger, "USER_REGISTER_FAILED", "system", "注册失败: 用户名或密码为空");
                return Result.fail("用户名或密码不能为空");
            }

            LogUtils.info(logger, () -> "尝试注册用户: " + user.getUsername());
            // 用户注册
            boolean success = userService.register(user);
            if (!success) {
                LogUtils.warn(logger, "注册失败: 用户名已存在，用户名: {}", user.getUsername());
                LogUtils.logBusiness(logger, "USER_REGISTER_FAILED", "system", "注册失败: 用户名已存在，用户名=" + user.getUsername());
                return Result.fail("用户名已存在");
            }
            
            LogUtils.logBusiness(logger, "USER_REGISTER_SUCCESS", "system", "用户注册成功: " + user.getUsername());
            LogUtils.logSecurityEvent(logger, "USER_REGISTERED", "新用户注册成功", "用户名: " + user.getUsername() + ", 角色: " + (user.getRole() != null ? user.getRole() : "默认"));
            LogUtils.logPerformance(logger, "register", startTime, System.currentTimeMillis());
            
            LogUtils.info(logger, () -> "注册请求处理完成，耗时=" + (System.currentTimeMillis() - startTime) + "ms");
            return Result.success(true);
        } catch (Exception e) {
            LogUtils.logApiError(logger, "POST", "/auth/register", e);
            LogUtils.error(logger, "注册过程发生异常: " + LogUtils.formatException(e));
            LogUtils.logBusiness(logger, "USER_REGISTER_FAILED", "system", "注册过程发生异常: " + LogUtils.formatException(e));
            LogUtils.logPerformance(logger, "register", startTime, System.currentTimeMillis());
            return Result.fail("注册失败: " + e.getMessage());
        }
    }

    /**
     * 用户登出
     */
    @PostMapping("/logout")
    @Operation(summary = "用户登出", description = "用户登出接口")
    public Result<Boolean> logout() {
        long startTime = System.currentTimeMillis();
        LogUtils.logBusiness(logger, "USER_LOGOUT_ATTEMPT", "system", "用户登出尝试");
        LogUtils.logSecurityEvent(logger, "USER_LOGOUT_REQUEST", "接收到用户登出请求", "请求来源: API接口");
        LogUtils.debug(logger, () -> "开始处理用户登出请求");
        
        try {
            LogUtils.logApiRequest(logger, "POST", "/auth/logout", null);
            
            // 登出逻辑（JWT是无状态的，客户端删除token即可）
            LogUtils.debug(logger, () -> "执行JWT无状态登出逻辑，清除客户端token即可");
            
            LogUtils.logBusiness(logger, "USER_LOGOUT_SUCCESS", "system", "用户登出成功");
            LogUtils.logSecurityEvent(logger, "USER_LOGOUT", "current_user", "用户登出成功");
            LogUtils.logPerformance(logger, "logout", startTime, System.currentTimeMillis());
            
            LogUtils.info(logger, () -> "登出请求处理完成，耗时=" + (System.currentTimeMillis() - startTime) + "ms");
            return Result.success(true);
        } catch (Exception e) {
            LogUtils.logApiError(logger, "POST", "/auth/logout", e);
            LogUtils.error(logger, "登出过程发生异常: " + LogUtils.formatException(e));
            LogUtils.logBusiness(logger, "USER_LOGOUT_FAILED", "system", "登出过程发生异常: " + LogUtils.formatException(e));
            LogUtils.logPerformance(logger, "logout", startTime, System.currentTimeMillis());
            return Result.fail("登出失败: " + e.getMessage());
        }
    }

    /**
     * 获取用户信息
     */
    @GetMapping("/userInfo")
    @Operation(summary = "获取用户信息", description = "获取当前登录用户信息")
    public Result<User> getUserInfo(@RequestHeader("Authorization") String token) {
        long startTime = System.currentTimeMillis();
        LogUtils.logBusiness(logger, "USER_INFO_ATTEMPT", "system", "获取用户信息尝试");
        LogUtils.logSecurityEvent(logger, "USER_INFO_REQUEST", "接收到获取用户信息请求", "请求包含Authorization头");
        LogUtils.debug(logger, () -> "开始处理获取用户信息请求");
        
        try {
            LogUtils.logApiRequest(logger, "GET", "/auth/userInfo", null);
            
            LogUtils.debug(logger, () -> "接收到Authorization头: " + (token != null ? "Bearer ****" : "空"));
            
            if (token == null || !token.startsWith("Bearer ")) {
                LogUtils.warn(logger, "获取用户信息失败: 无效的token");
                LogUtils.logBusiness(logger, "USER_INFO_FAILED", "system", "获取用户信息失败: 无效的token格式");
                return Result.fail("无效的token");
            }
            
            String jwtToken = token.substring(7); // 去掉"Bearer "前缀
            LogUtils.debug(logger, () -> "解析JWT令牌获取用户信息");
            String username = jwtTokenUtil.getUsernameFromToken(jwtToken);
            
            if (username == null) {
                LogUtils.warn(logger, "获取用户信息失败: 无法从token中获取用户名");
                LogUtils.logBusiness(logger, "USER_INFO_FAILED", "system", "获取用户信息失败: 无法从token中获取用户名");
                return Result.fail("无效的token");
            }
            
            LogUtils.info(logger, () -> "获取用户信息: " + username);
            User user = userService.getByUsername(username);
            
            if (user == null) {
                LogUtils.warn(logger, "获取用户信息失败: 用户不存在，用户名: {}", username);
                LogUtils.logBusiness(logger, "USER_INFO_FAILED", "system", "获取用户信息失败: 用户不存在，用户名=" + username);
                return Result.fail("用户不存在");
            }
            
            LogUtils.info(logger, () -> "成功获取用户信息: 用户名=" + username + ", 用户ID=" + user.getId() + ", 角色=" + user.getRole() + ", 状态=" + user.getStatus());
            LogUtils.logBusiness(logger, "USER_INFO_SUCCESS", "system", "成功获取用户信息: 用户名=" + username);
            LogUtils.logPerformance(logger, "getUserInfo", startTime, System.currentTimeMillis());
            
            LogUtils.info(logger, () -> "获取用户信息请求处理完成，耗时=" + (System.currentTimeMillis() - startTime) + "ms");
            return Result.success(user);
        } catch (Exception e) {
            LogUtils.logApiError(logger, "GET", "/auth/userInfo", e);
            LogUtils.error(logger, "获取用户信息过程发生异常: " + LogUtils.formatException(e));
            LogUtils.logBusiness(logger, "USER_INFO_FAILED", "system", "获取用户信息过程发生异常: " + LogUtils.formatException(e));
            LogUtils.logPerformance(logger, "getUserInfo", startTime, System.currentTimeMillis());
            return Result.fail("获取用户信息失败: " + e.getMessage());
        }
    }
}